package tools.data;

import constants.ServerConstants;

import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class LittleEndianAccessor {
    private ByteArrayByteStream bs;

    public LittleEndianAccessor(ByteArrayByteStream bs) {
        this.bs = bs;
    }

    public int readByteAsInt() {
        return this.bs.readByte();
    }

    public byte readByte() {
        return (byte) this.bs.readByte();
    }

    public int readInt() {
        int byte1 = this.bs.readByte();
        int byte2 = this.bs.readByte();
        int byte3 = this.bs.readByte();
        int byte4 = this.bs.readByte();
        return (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1;
    }

    public short readShort() {
        int byte1 = this.bs.readByte();
        int byte2 = this.bs.readByte();
        return (short) ((byte2 << 8) + byte1);
    }

    public int readUShort() {
        int quest = this.readShort();
        if (quest < 0) {
            quest += 65536;
        }
        return quest;
    }

    public char readChar() {
        return (char) this.readShort();
    }

    public long readLong() {
        long byte1 = (long) this.bs.readByte();
        long byte2 = (long) this.bs.readByte();
        long byte3 = (long) this.bs.readByte();
        long byte4 = (long) this.bs.readByte();
        long byte5 = (long) this.bs.readByte();
        long byte6 = (long) this.bs.readByte();
        long byte7 = (long) this.bs.readByte();
        long byte8 = (long) this.bs.readByte();
        return (byte8 << 56) + (byte7 << 48) + (byte6 << 40) + (byte5 << 32) + (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1;
    }

    public float readFloat() {
        return Float.intBitsToFloat(this.readInt());
    }

    public double readDouble() {
        return Double.longBitsToDouble(this.readLong());
    }

    public String readAsciiString(int n) {
        try {
            byte[] ret = new byte[n];
            for (int x = 0; x < n; ++x) {
                ret[x] = this.readByte();
            }
            return new String(ret, ServerConstants.MAPLE_TYPE.getANSI());
        } catch (UnsupportedEncodingException ex) {
            System.err.println(ex);
            return "";
        }
    }

    public long getBytesRead() {
        return this.bs.getBytesRead();
    }

    public String readMapleAsciiString() {
        return this.readAsciiString((int) this.readShort());
    }

    public Point readPos() {
        int x = this.readShort();
        int y = this.readShort();
        return new Point(x, y);
    }

    public byte[] read(int num) {
        byte[] ret = new byte[num];
        for (int x = 0; x < num; ++x) {
            ret[x] = this.readByte();
        }
        return ret;
    }

    public void unReadByte() {
        this.bs.unReadByte();
    }

    public void unReadInt() {
        for (int byte_ = 0; byte_ < 4; ++byte_) {
            this.bs.unReadByte();
        }
    }

    public void unReadShort() {
        for (int byte_ = 0; byte_ < 2; ++byte_) {
            this.bs.unReadByte();
        }
    }

    public void unReadLong() {
        for (int byte_ = 0; byte_ < 8; ++byte_) {
            this.bs.unReadByte();
        }
    }

    public void unReadAsciiString(int n) {
        for (int byte_ = 0; byte_ < n; ++byte_) {
            this.bs.unReadByte();
        }
    }

    public void unReadPos() {
        for (int byte_ = 0; byte_ < 4; ++byte_) {
            this.bs.unReadByte();
        }
    }

    public void unRead(int num) {
        for (int byte_ = 0; byte_ < num; ++byte_) {
            this.bs.unReadByte();
        }
    }

    public byte readLastByte() {
        return (byte) this.bs.readLastByte();
    }

    public int readLastInt() {
        this.unReadInt();
        int byte1 = this.bs.readByte();
        int byte2 = this.bs.readByte();
        int byte3 = this.bs.readByte();
        int byte4 = this.bs.readByte();
        return (byte4 << 24) + (byte3 << 16) + (byte2 << 8) + byte1;
    }

    public short readLastShort() {
        this.unReadShort();
        int byte1 = this.bs.readByte();
        int byte2 = this.bs.readByte();
        return (short) ((byte2 << 8) + byte1);
    }

    public long readLastLong() {
        this.unReadLong();
        int byte1 = this.bs.readByte();
        int byte2 = this.bs.readByte();
        int byte3 = this.bs.readByte();
        int byte4 = this.bs.readByte();
        long byte5 = (long) this.bs.readByte();
        long byte6 = (long) this.bs.readByte();
        long byte7 = (long) this.bs.readByte();
        long byte8 = (long) this.bs.readByte();
        return (byte8 << 56) + (byte7 << 48) + (byte6 << 40) + (byte5 << 32) + (long) (byte4 << 24) + (long) (byte3 << 16) + (long) (byte2 << 8) + (long) byte1;
    }

    public String readLastAsciiString(int n) {
        try {
            for (int y = 0; y < n; ++y) {
                this.unReadByte();
            }
            byte[] ret = new byte[n];
            for (int x = 0; x < n; ++x) {
                ret[x] = this.readByte();
            }
            return new String(ret, ServerConstants.MAPLE_TYPE.getANSI());
        } catch (UnsupportedEncodingException ex) {
            System.err.println(ex);
            return "";
        }
    }

    public Point readLastPos() {
        this.unReadInt();
        short x = this.readShort();
        short y = this.readShort();
        return new Point((int) x, (int) y);
    }

    public byte[] readLastBytes(int num) {
        for (int byte_ = 0; byte_ < num; ++byte_) {
            this.bs.unReadByte();
        }
        byte[] ret = new byte[num];
        for (int x = 0; x < num; ++x) {
            ret[x] = this.readByte();
        }
        return ret;
    }

    public long available() {
        return this.bs.available();
    }

    @Override
    public String toString() {
        return this.bs.toString();
    }

    public String toString(boolean b) {
        return this.bs.toString(b);
    }

    public void seek(long offset) {
        try {
            this.bs.seek(offset);
        } catch (IOException e) {
            System.err.println("Seek failed" + e);
        }
    }

    public long getPosition() {
        return this.bs.getPosition();
    }

    public void skip(int num) {
        this.seek(this.getPosition() + (long) num);
    }

    public String readNullTerminatedAsciiString() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while (true) {
            byte b = this.readByte();
            if (b == 0) {
                break;
            }
            baos.write((int) b);
        }
        byte[] buf = baos.toByteArray();
        char[] chrBuf = new char[buf.length];
        for (int x = 0; x < buf.length; ++x) {
            chrBuf[x] = (char) buf[x];
        }
        return String.valueOf(chrBuf);
    }
}
